package com.ruoyi.system.service.impl;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.system.config.WebSocketServer;
import com.ruoyi.common.core.domain.ThridApiResponse;
import com.ruoyi.common.exception.ServiceException;

import com.ruoyi.system.domain.PCabinet;
import com.ruoyi.system.service.IPCabinetService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.PTaskMapper;
import com.ruoyi.system.domain.PTask;
import com.ruoyi.system.service.IPTaskService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 任务管理Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-05-21
 */
@Service
public class PTaskServiceImpl extends ServiceImpl<PTaskMapper, PTask> implements IPTaskService
{
    private static final Logger logger = LoggerFactory.getLogger(PTaskServiceImpl.class);

    @Autowired
    private IPCabinetService cabinetService;
    @Autowired
    private RuoYiConfig ruoYiConfig;
    @Autowired
    WebSocketServer webSocketServer;
    /**
     * 查询任务管理
     * 
     * @param id 任务管理主键
     * @return 任务管理
     */
    @Override
    public PTask selectPTaskById(Long id)
    {
        return baseMapper.selectPTaskById(id);
    }

    /**
     * 查询任务管理列表
     * 
     * @param pTask 任务管理
     * @return 任务管理
     */
    @Override
    public List<PTask> selectPTaskList(PTask pTask)
    {
        return baseMapper.selectPTaskList(pTask);
    }

    /**
     * 新增任务管理
     * 
     * @param pTask 任务管理
     * @return 结果
     */
    @Override
    @Transactional
    public String insertPTask(PTask pTask)
    {
        QueryWrapper<PTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("sid", pTask.getSid());
        queryWrapper.eq("status", "0");
        PTask task = baseMapper.selectOne(queryWrapper);
        if (task != null) {
            throw new  ServiceException("有密码未使用");
        }

        Random random = new Random();
        int randomNum = random.nextInt(10000);
        String randomPart = String.format("%04d", randomNum);
        pTask.setActionId(new Date().getTime()+randomPart);

        StringBuilder dynamicPassword = new StringBuilder();

        // 生成后5位数字
        for (int i = 0; i < 6; i++) {
            dynamicPassword.append(random.nextInt(10)); // 0-9
        }

        QueryWrapper<PCabinet> queryWrappers = new QueryWrapper<>();
        queryWrappers.eq("code", pTask.getSid());
        PCabinet one = cabinetService.getOne(queryWrappers);
        pTask.setCabinetName(one.getCabinetName());
        pTask.setStatus("0");
        pTask.setDyPass(dynamicPassword.toString());
        // 调用设备动态密码接口
        if (!sendDynamicPassword(pTask)) {
            throw new ServiceException("动态密码下发失败");
        }
        baseMapper.insert(pTask);
        return dynamicPassword.toString();
    }


    /**
     * 发送动态密码到设备
     * @param pTask 任务对象
     * @return 发送结果
     */
    private boolean sendDynamicPassword(PTask pTask) {
        // 1. 获取设备信息
        QueryWrapper<PCabinet> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", pTask.getSid());
        PCabinet deviceInfo = cabinetService.getOne(queryWrapper);
        if (deviceInfo == null) {
            logger.error("设备不存在，: {}", deviceInfo.getCode());
            throw new ServiceException(deviceInfo.getCode()+"不存在");
        }

        // 2. 构建设备URL

        String apiUrl = "http://"+deviceInfo.getCabinetIp()+":"+deviceInfo.getCabinetPort() + "/device/dyPass";

        // 3. 创建请求对象
        Map<String, String> requestData = new HashMap<>();
        requestData.put("SID", deviceInfo.getCode());
        requestData.put("DyPass", pTask.getDyPass()); // 假设PTask中有dynamicPassword字段

        // 4. 发送请求
        try {
            logger.info("向设备[{}]发送动态密码，url:{} 参数:{}", deviceInfo.getCode(),apiUrl,requestData);
            HttpResponse response = HttpRequest.post(apiUrl)
                    .body(JSONUtil.toJsonStr(requestData))
                    .contentType("application/json")
                    .timeout(5000)
                    .execute();

            if (response.isOk()) {
                String body = response.body();
                // 解析响应
                ThridApiResponse resultObj = JSONUtil.toBean(body, ThridApiResponse.class);
                logger.info("下发密码响应结果：{},{},{}", resultObj.getBizCode(),resultObj.getBizMsg(),resultObj.getReceiverTime());
                if ("SUCCESS".equals(resultObj.getBizCode())) {
                    return true;
                }
            } else {
                logger.error("设备[{}]HTTP请求失败，状态码: {}",
                        deviceInfo.getCode(), response.getStatus());
            }
        } catch (Exception e) {
            logger.error("设备[{}]动态密码请求异常: {}", deviceInfo.getCode(), e.getMessage(), e);
        }

        return false;
    }

    /**
     * 修改任务管理
     * 
     * @param pTask 任务管理
     * @return 结果
     */
    @Override
    @Transactional
    public int updatePTask(PTask pTask)
    {
        boolean passResult = sendStatus(pTask.getId());;
        if (!passResult) {
            // 处理密码下发失败的情况，可以选择记录日志或抛出异常
            logger.error("动态密码下发失败，柜子编号: {}", pTask.getSid());
            throw new ServiceException("动态密码下发失败");
        }

        return baseMapper.updatePTask(pTask);
    }

    /**
     * 批量删除任务管理
     * 
     * @param ids 需要删除的任务管理主键
     * @return 结果
     */
    @Override
    public int deletePTaskByIds(Long[] ids)
    {
        return baseMapper.deletePTaskByIds(ids);
    }

    /**
     * 删除任务管理信息
     * 
     * @param id 任务管理主键
     * @return 结果
     */
    @Override
    public int deletePTaskById(Long id)
    {
        return baseMapper.deletePTaskById(id);
    }

    @Override
    public boolean sendStatus(Long id) {
        PTask pTask = baseMapper.selectById(id);
        // 1. 获取设备信息
        QueryWrapper<PCabinet> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", pTask.getSid());
        PCabinet deviceInfo = cabinetService.getOne(queryWrapper);
        if (deviceInfo == null) {
            logger.error("设备不存在，: {}", deviceInfo.getCode());
            throw new ServiceException(deviceInfo.getCode()+"不存在");
        }

        // 2. 构建设备URL

        String apiUrl = "http://"+deviceInfo.getCabinetIp()+":"+deviceInfo.getCabinetPort() + "/device/actionResp";

        // 3. 创建请求对象
        Map<String, String> requestData = new HashMap<>();
        requestData.put("SID", pTask.getSid());
        requestData.put("ActionID", pTask.getActionId()); // 假设PTask中有dynamicPassword字段
        requestData.put("resp", pTask.getStatus());
        // 4. 发送请求
        try {
            logger.info("向设备[{}]发送密码验证状态.url:{},参数:{}", deviceInfo.getCode(),apiUrl,requestData);

            HttpResponse response = HttpRequest.post(apiUrl)
                    .body(JSONUtil.toJsonStr(requestData))
                    .contentType("application/json")
                    .timeout(5000)
                    .execute();

            if (response.isOk()) {
                String body = response.body();

                // 解析响应
                ThridApiResponse resultObj = JSONUtil.toBean(body, ThridApiResponse.class);
                logger.info("下发密码验证状态响应结果：{},{},{}", resultObj.getBizCode(),resultObj.getBizMsg(),resultObj.getReceiverTime());
                if ("SUCCESS".equals(resultObj.getBizCode())) {
                    return true;
                }
            } else {
                logger.error("设备[{}]HTTP请求失败，状态码: {}",
                        deviceInfo.getCode(), response.getStatus());
            }
        } catch (Exception e) {
            logger.error("设备[{}]动态密码请求异常: {}", deviceInfo.getCode(), e.getMessage(), e);
        }

        return false;
    }

    @Override
    @Transactional
    public void scanUpdateTaskStatus() {
        // 1. 查询所有状态为0的任务
        QueryWrapper<PTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", "0");
        List<PTask> pTasks = baseMapper.selectList(queryWrapper);

        // 2. 筛选出过期任务
        List<PTask> expireTask = new ArrayList<>();
        if(pTasks != null && !pTasks.isEmpty()){
            for (PTask pTask : pTasks) {
                Date createTime = pTask.getCreateTime();
                Date currentTime = new Date();
                long diffInMillis = currentTime.getTime() - createTime.getTime();
                long diffInMinutes = TimeUnit.MILLISECONDS.toMinutes(diffInMillis);

                if (diffInMinutes >= ruoYiConfig.getDyPassExpire()) {
                    logger.info("密码{}已过期，创建时间：{}，已超过{}分钟",
                            pTask.getDyPass(), createTime, diffInMinutes-ruoYiConfig.getDyPassExpire());
                    expireTask.add(pTask);
                }
            }
        }

        // 3. 更新过期任务状态
        if(!expireTask.isEmpty()){
            UpdateWrapper<PTask> updateWrapper = new UpdateWrapper<>();
            List<Long> expireTaskIds = expireTask.stream()
                    .map(PTask::getId)
                    .collect(Collectors.toList());

            updateWrapper.in("id", expireTaskIds)
                    .set("status", "1");
            int rows = baseMapper.update(null, updateWrapper);
            logger.info("成功更新{}个过期任务状态", rows);
        }

        // 4. 重新查询最新的状态为0的数据
        QueryWrapper<PTask> freshQueryWrapper = new QueryWrapper<>();
        freshQueryWrapper.eq("status", "0");
        List<PTask> freshTasks = baseMapper.selectList(freshQueryWrapper);

        // 5. 通过WebSocket发送最新数据
        Map<String, Object> jsonResult = new HashMap<>();
        jsonResult.put("dypass", freshTasks);
        webSocketServer.sendInfo("1", JSONUtil.toJsonStr(jsonResult));
    }

}
